# Define the couchapp design doc
# Change the last part of the _id value to something specific to the couchapp.
#
design_doc =
	_id: '_design/app'

	rewrites: [
		{ from: "/", to: 'index.html' }
		{ from: "/*", to: '*' }
		{ from: "/api", to: '../../' }
		{ from: "/api/*", to: '../../*' }
	]

	validate_doc_update: (newDoc, oldDoc, userCtx) ->
		if newDoc._deleted is true and userCtx.roles.indexOf('_admin') is -1
			throw "Only admin can delete documents on this database."

	views:
		
		donations:
			map: (doc) ->
				if doc.type is 'donation'
					emit doc.donor_id, doc
		search_org:
			map: (doc) ->
				# Helper function to match for keywords in a given array of words
				matches = (_array, _string) -> if _array.indexOf(_string) isnt -1 then return true else return false
				
				# Helper function that returns a substring of a word or returns false if it's smaller than a specified number of characters
				substrIndex = (_str, _cut, _i) ->
					txt = _str.toLowerCase().slice(0, _str.length - _i)
					if txt.length <= _cut then return false else return txt
					
				if doc.org is true and doc.type is 'donor'
					
					# Index specific full name search in format LASTNAME,FIRSTNAME
					_str = "#{doc.last_name}, #{doc.first_name}"
					for i of _str
						txt = _str.toLowerCase().slice(0, _str.length - i)
						# Do not index anything string shorter than the comma, because that's likely
						# already been indexed
						continue if txt.indexOf(',') is -1
						emit txt, doc
					
					# Parse through all other properties
					for k of doc
						# Create an array for properties that should not be indexed
						_omit = ['city', 'org', 'province', 'type', '_id', '_rev']
						
						# Fine Index is an array for really fine indexing (substring of a string that doesn't have to start
						# from the first character, Whole Index is an array of properties that should just be indexed as a
						# whole word. (The native method) Though defined here and implemented subsequently, these are not used
						# (for now).
						_fineIndex = _wholeIndex = []
						
						# Continue to next loop if the keyword matches
						continue if matches(_omit, k)
						
						# Emit natively if property is to be indexed as a whole word
						if matches(_wholeIndex, k)
							emit doc[k].toLowerCase(), doc
							continue
						
						# If property is postal code, then we'll parse the postal code to uniformly index them as 6 characters 
						# with no spaces or dashes	
						if k is 'postal_code'
							(if not (txt = substrIndex(x, 3, i)) then continue else emit txt, doc) for i of x = doc[k].replace(/[ -]/, "")
							continue
						
						# IF the property is telephone then we'll index the number in two sets. The first set indexes including the area
						# code and has a cutoff length of a 6, so (604) 538-5930 will start indexing from 6045385 to the full phone number
						# The second set will omit the first 3 area code numbers and index with a cutoff length of 3 so the above number
						# would start indexing from 5385 to the full phone number. If the full phone number is only 7 number, then skip the 
						# first set and index the second set directly
						if k.match('tel_')
							x = doc[k].replace(/[ \-\(\)]/g, "")
							if x.length > 7 then _cutLength = 6 else _cutLength = 3
							(if not (txt = substrIndex(x, _cutLength, i)) then continue else emit txt, doc) for i of x						
							(if not (txt = substrIndex(x, 3, i)) then continue else emit txt, doc) for i of x = x.slice(3, x.length)
							continue
						
						if k.match(/street_address|org_name/)
							x = doc[k].toLowerCase().split(' ')
							y = []
							y.push(x.slice(i).join(" ")) for i of x
							for i of y
								for j of y[i]
									txt = y[i].slice(0, y[i].length - j)
									continue if txt.charAt(txt.length - 1) is " "
									emit txt, doc
							continue
							
						# For everything else, index with a cutoff length of 2. However, allow last name to be indexed with 2 characters
						# To avoid neglecting names like Ho, Li, or Ng
						for i of x = doc[k]
							txt = x.toLowerCase().slice(0, x.length - i)
							continue if txt.length <= 2 and k isnt 'last_name'
							
							# Fine indexing implementaion, but is not used currently
							if matches(_fineIndex, k)
								for j of txt
									continue if txt.slice(j).length <= 2
									emit txt.slice(j), doc
								continue
							continue if txt.length <= 1 
							emit txt, doc		
								
		search:
			map: (doc) ->
				# Helper function to match for keywords in a given array of words
				matches = (_array, _string) -> if _array.indexOf(_string) isnt -1 then return true else return false
				
				# Helper function that returns a substring of a word or returns false if it's smaller than a specified number of characters
				substrIndex = (_str, _cut, _i) ->
					txt = _str.toLowerCase().slice(0, _str.length - _i)
					if txt.length <= _cut then return false else return txt
					
				if doc.org is false and doc.type is 'donor'
					
					# Index specific full name search in format LASTNAME,FIRSTNAME
					_str = "#{doc.last_name}, #{doc.first_name}"
					for i of _str
						txt = _str.toLowerCase().slice(0, _str.length - i)
						# Do not index anything string shorter than the comma, because that's likely
						# already been indexed
						continue if txt.indexOf(',') is -1
						emit txt, doc
					
					# Parse through all other properties
					for k of doc
						# Create an array for properties that should not be indexed
						_omit = ['city', 'org', 'province', 'type', '_id', '_rev']
						
						# Fine Index is an array for really fine indexing (substring of a string that doesn't have to start
						# from the first character, Whole Index is an array of properties that should just be indexed as a
						# whole word. (The native method) Though defined here and implemented subsequently, these are not used
						# (for now).
						_fineIndex = _wholeIndex = []
						
						# Continue to next loop if the keyword matches
						continue if matches(_omit, k)
						
						# Emit natively if property is to be indexed as a whole word
						if matches(_wholeIndex, k)
							emit doc[k].toLowerCase(), doc
							continue
						
						# If property is postal code, then we'll parse the postal code to uniformly index them as 6 characters 
						# with no spaces or dashes	
						if k is 'postal_code'
							(if not (txt = substrIndex(x, 3, i)) then continue else emit txt, doc) for i of x = doc[k].replace(/[ -]/, "")
							continue
						
						# IF the property is telephone then we'll index the number in two sets. The first set indexes including the area
						# code and has a cutoff length of a 6, so (604) 538-5930 will start indexing from 6045385 to the full phone number
						# The second set will omit the first 3 area code numbers and index with a cutoff length of 3 so the above number
						# would start indexing from 5385 to the full phone number. If the full phone number is only 7 number, then skip the 
						# first set and index the second set directly
						if k.match('tel_')
							x = doc[k].replace(/[ \-\(\)]/g, "")
							if x.length > 7 then _cutLength = 6 else _cutLength = 3
							(if not (txt = substrIndex(x, _cutLength, i)) then continue else emit txt, doc) for i of x						
							(if not (txt = substrIndex(x, 3, i)) then continue else emit txt, doc) for i of x = x.slice(3, x.length)
							continue
						
						if k.match('street_address')
							x = doc[k].toLowerCase().split(' ')
							y = []
							y.push(x.slice(i).join(" ")) for i of x
							for i of y
								for j of y[i]
									txt = y[i].slice(0, y[i].length - j)
									continue if txt.charAt(txt.length - 1) is " "
									emit txt, doc
							continue
							
						# For everything else, index with a cutoff length of 2. However, allow last name to be indexed with 2 characters
						# To avoid neglecting names like Ho, Li, or Ng
						for i of x = doc[k]
							txt = x.toLowerCase().slice(0, x.length - i)
							continue if txt.length <= 2 and k isnt 'last_name'
							
							# Fine indexing implementaion, but is not used currently
							if matches(_fineIndex, k)
								for j of txt
									continue if txt.slice(j).length <= 2
									emit txt.slice(j), doc
								continue
							continue if txt.length <= 1 
							emit txt, doc


# Define the attachments folder for the couchapp
# Change 'attachments' to the specific folder name.
att_folder = (require 'path').join __dirname, 'attachments'

# Load the attachments for the design document to the couchdb server
(require 'couchapp').loadAttachments design_doc, att_folder

# Export the design doc object for other nodejs modules to use
module.exports = design_doc
